feat: add grouped exposure views#624
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
🚅 Deployed to the euler-lite-pr-624 environment in euler-lite
|
Polish the vault open interest graph with card-based nodes, responsive mobile stacking, and data-aware spacing for dense collateral sets.
Remove the standalone vault-page open interest chart and add a compact Explore matrix Open Interest view grouped by backing asset, including duplicate-vault counts for aggregated exposures.
Limit the matrix Open Interest view to the first four borrow-vault cards by default and add a Show more/Show less control for dense markets.
Keep every borrow-vault card visible in the matrix Open Interest view, but collapse each card's backing-asset rows after the top three with a per-card Show more control.
Center the per-card Show more control in the matrix Open Interest view.
Show token avatars next to borrow and backing asset symbols in the matrix Open Interest view.
Drops the redundant 'Can be used as collateral' field from vault overview surfaces now that collateral exposure is covered by the matrix/open-interest work.
Adds shared backing-asset grouping for exposure data and applies it across lend rows, lend exposure details, earn rows, and earn vault exposure sections.
Hides backing-asset group headers when an exposure section only has one backing asset, leaving the underlying vault rows as the primary content.
Removes visible backing-asset symbol lists from lend and earn list rows so the compact exposure datapoints stay to count plus token avatars.
Flatten collateral and earn exposure detail sections so vault rows render without backing-asset headers. Keep grouped ordering and collapsed show-more behavior, with counts based on hidden rows.
Adds a Chart.js doughnut view to the borrow pair overview, using the existing open-interest endpoint and grouped backing-asset model. Includes the total borrowed amount, per-asset percentages, values, and grouped vault counts.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Leonard review — PR #624
Verdict: COMMENT — no blocking findings found on head 80f23665f8aa9ebd291d3ac2e7a5842f9400dfcf. I’m leaving this as a comment rather than approval because approval state was not requested.
Scope reviewed:
- Grouped collateral exposure/open-interest utilities and tests.
- Shared
useCollateralOpenInterest()loader, stale-chain handling, and V3 proxy allowlist for/v3/evk/vaults/open-interest/by-collateral. - Lend vault grouped Collateral exposure UI and borrow-pair Open interest UI on the PR Railway preview.
- Scalability / maintainability hygiene pass across sibling lend/earn/borrow exposure surfaces.
- Existing bot/reviewer feedback. CodeRabbit’s visible top-level note says auto-review was skipped; I did not find a material active bot claim to carry forward.
Validation run:
npm run test:run -- tests/utils/open-interest.test.ts tests/utils/vault/collateral-exposure.test.ts tests/composables/useCollateralOpenInterest.test.ts tests/server/v3-proxy.test.ts— passed, 30 tests.npm run typecheck— passed.npm run build— passed, warnings only.- Browser visual smoke on the PR preview:
- Desktop
/lend/0xba98fC35C9dfd69178AD5dcE9FA29c64554783b5?network=1: expanded Collateral exposure for Sentora PYUSD; live exposure rows rendered with Max LTV / Liquidation LTV and collapsed extra row control. - Mobile same route: opened Vault information and expanded Collateral exposure; live exposure rows rendered in the narrow modal layout.
- Desktop
/borrow/0xba98fC35C9dfd69178AD5dcE9FA29c64554783b5/0xAB2726DAf820Aa9270D14Db9B18c8d187cbF2f30?network=1: Open interest surface loaded; by-collateral open-interest API returned 200.
- Desktop
Visual evidence:
- Desktop lend vault Collateral exposure: https://gist.githubusercontent.com/LeonardEulerXYZ/990bfbf0cb45c5fa1aa33938d02fd22d/raw/3df81580cbeafca5944dd505519f47d5f845b564/euler-xyz-euler-lite-pr624-pr624-desktop-lend-pyusd-collateral.png
- Mobile lend vault Collateral exposure: https://gist.githubusercontent.com/LeonardEulerXYZ/990bfbf0cb45c5fa1aa33938d02fd22d/raw/5189c2acb718366e894b4905b403b9bfabcf0099/euler-xyz-euler-lite-pr624-pr624-mobile-lend-pyusd-collateral.png
- Desktop borrow pair Open interest: https://gist.githubusercontent.com/LeonardEulerXYZ/990bfbf0cb45c5fa1aa33938d02fd22d/raw/f308d55366d91714acc91a0be79daf8c2f972ffe/euler-xyz-euler-lite-pr624-pr624-desktop-borrow-pyusd-usdc-open-interest.png
Review notes:
- The two earlier Leonard blockers are resolved in this head: the shared loader now guards stale overlapping chain responses, and the borrow-pair Open interest block uses the shared collateral open-interest path rather than maintaining a duplicate fetch/cache path.
- The grouped exposure abstraction is in shared utilities with focused unit coverage rather than being embedded as one-off component logic. I checked sibling lend-row, lend-vault, earn-row/earn-vault, and borrow-pair exposure/open-interest consumers; the remaining split is intentional presentation shape, not duplicated business logic.
- No wallet/signing path was exercised. This pass covered read-only route/API/visual behavior for the grouped exposure surfaces.
Avoid duplicate Vue keys when an exposure summary contains separate buckets for the same asset address, such as an active asset and its idle bucket.
Treat unavailable exposure pricing and missing live splits as unavailable instead of zero-valued exposure, and add focused formatter coverage.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Leonard review — PR #624
Verdict: REQUEST_CHANGES on head 04e01cf3144457e78a01b69fb56a26d228bab828.
Thanks for the latest pass. The two previous blockers appear resolved: useCollateralOpenInterest now ignores stale overlapping chain loads, and the vault overview open-interest section now uses the shared composable rather than its own direct fetch path.
I found one remaining consistency blocker in the newly-added stats-matrix exposure surface: when a vault is utilized but the API lacks the collateral split, the matrix silently drops that vault from exposureItemsByVault while the global exposure state remains ready. That renders the stats cell as - rather than Unavailable, which makes “data missing” look like “no exposure” for exactly the high-utilization vaults where this feature is most useful. I left the concrete note inline.
Validation performed:
npm run test:run -- tests/composables/useCollateralOpenInterest.test.ts tests/utils/vault/exposure-display.test.ts tests/utils/vault/collateral-exposure.test.ts✅npm run typecheck✅npm run build✅- Targeted ESLint over PR-changed source/test files ✅
- Full
npm run lintis still blocked by existing repository-wide lint debt outside this PR; targeted lint for the changed files passed. - Railway preview browser visual smoke at
/lend?network=1on desktop and mobile ✅: the route loaded real content, the newExposurecolumn/rows were visible, and no material page error state was observed.
Screenshot evidence:
- Desktop lend list, exposure column visible: https://gist.githubusercontent.com/LeonardEulerXYZ/423903624e3a1db461124cb483167a88/raw/a2beec46b7c9f4f45ed71d8d9b9c69dc49d47016/euler-xyz-euler-lite-pr624-pr624-lend-desktop.png
- Mobile lend list, exposure row visible: https://gist.githubusercontent.com/LeonardEulerXYZ/423903624e3a1db461124cb483167a88/raw/3a70f7816b4f1d2e69718119ee9fead994c46036/euler-xyz-euler-lite-pr624-pr624-lend-mobile.png
Scalability / maintainability hygiene pass:
- Good: the open-interest loader and exposure display/grouping logic are now shared across the card, overview, earn, and modal surfaces, with focused tests around the reusable utilities and stale-load behavior.
- Remaining issue: the stats matrix adds a sibling consumer with its own per-vault omission behavior for missing collateral splits. That should share the same “missing utilized split => unavailable” display invariant as the other grouped-exposure surfaces, rather than degrading to an empty ready state.
Bot/reviewer feedback pass:
- I did not find active CodeRabbit findings to verify on the current head.
- Prior Leonard blockers were rechecked against the current diff and are no longer applicable; no Leonard-owned inline comments were present via the review-comments API to delete.
Smoke coverage: browser visual smoke + mobile smoke on the Railway preview; no wallet/signing smoke, since this PR changes read-only exposure presentation and proxy allowlisting, not transaction construction.
Carry per-vault exposure value state in the stats matrix so missing price or utilized split data renders as unavailable instead of an empty ready exposure.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Leonard review — PR #624
Verdict: COMMENT — no blocking findings found on head 792e9e748f701863359466eeba03ce0f5d8ea8ef. I’m leaving this as a comment rather than approval because this reviewer request did not explicitly ask for approval state.
Compared against parent branch feature/lite-215-convert-vault-page-sections-to-accordion-style / PR #617. This pass was an incremental re-review of the child delta since my previous blocking review on 04e01cf3144457e78a01b69fb56a26d228bab828; the only new diff is components/entities/vault/discovery/DiscoveryMarketAttributeMatrix.vue.
What changed in this head
- The stats matrix now carries a per-vault exposure entry with both
itemsandvalueState. - Missing USD input or missing utilized collateral split now records
valueState: 'unavailable'for that vault instead of omitting it from the map. VaultExposureSummarynow receives the per-vault state, and matrix celldata-valuereturnsloading/unavailablewhen the exposure cell is not ready.
This resolves my previous blocker: a utilized vault with a missing collateral split should no longer degrade to an empty ready value (-) merely because the global open-interest loader is ready.
Validation performed
git diff --check origin/feature/lite-215-convert-vault-page-sections-to-accordion-style...HEAD— passed.npm run test:run -- tests/composables/useCollateralOpenInterest.test.ts tests/utils/vault/exposure-display.test.ts tests/utils/vault/collateral-exposure.test.ts tests/server/v3-proxy.test.ts— passed, 32 tests.npm run typecheck— passed.- Targeted ESLint over the changed stats-matrix/exposure files and related tests — passed.
npm run build— passed; existing Vite/Rollup chunk/comment warnings only.- Headed Chromium/Xvfb route smoke on the current PR Railway preview:
/explore?network=1, KPK/Securitize market expanded, Matrix → Stats selected.- Stats matrix rendered with the new
Exposurecolumn and exposure cells populated for live assets; no material page errors observed.
- Malicious/supply-chain scan over the incremental diff: no executable script/workflow/dependency/secret/exfiltration indicators found.
Review notes
- Prior Leonard blockers were rechecked against the current diff and are resolved.
- CodeRabbit’s visible comment is still a skipped-review status for the non-default base branch; I found no active CodeRabbit finding to verify.
- Wallet/signing coverage was not run; this PR remains read-only display/data aggregation work and does not modify transaction construction.
Smoke coverage: browser route/visual smoke on the Railway preview; no wallet/signing smoke.
|
@/tmp/pr624-current-screenshot-comment.md |
Moves markets listed links into their own row in the exposure popup so Earn vault users can scan and click listed markets more easily.
Omits exposure market source labels when no market route exists, avoiding duplicate non-clickable escrow asset entries in Earn exposure popovers.
Adds punctuation and reduces the label gap so exposure market links do not appear offset in the popover.
Renders exposure market links as inline units so the first link and commas do not appear separated by extra spacing.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Leonard review — PR #624
Verdict: COMMENT — no blocking findings found on head 243c4e456a47ced60ecfba3a8187f7f9c915aa0b. I’m leaving this as a comment rather than approval because approval state was not requested.
Compared against parent branch feature/lite-215-convert-vault-page-sections-to-accordion-style / PR #617. This pass focused on the current grouped exposure views, the latest Earn/exposure source behavior, and the previously-reviewed shared loader/matrix invariants.
What I checked
- PR metadata, current diff, surrounding code, and previous Leonard review artifacts.
- Existing Leonard comments/reviews and current review-comment API state.
- Bot/reviewer feedback: CodeRabbit’s visible status remains a skipped-review note for this non-default target; I found no active bot code finding to verify or carry forward.
- Scalability / maintainability hygiene pass across the sibling grouped-exposure consumers: Lend rows, Lend vault overview, Earn rows, Earn vault overview/stats/exposure, Borrow pair open-interest, and Explore matrix stats.
Validation performed
npm run test:run -- tests/components/base/BaseExposureSourcesModal.test.ts tests/components/entities/vault/overview/VaultOverviewEarnBlockStats.test.ts tests/utils/vault/exposure-display.test.ts— passed for the matching focused suite that Vitest selected, 6 tests.npm run typecheck— passed.npm run build— passed, warnings only.- Headed Chromium/Xvfb browser visual smoke on the current PR build:
- Desktop
/earn?network=1: expanded Euler Prime and opened the Exposure modal; grouped exposure rows and Markets listed links rendered. - Mobile
/earn?network=1at 390px width: opened the same Exposure modal; narrow layout kept exposure rows and source links visible without blank/loading/error state. - Desktop
/explore?network=1: expanded the Securitize/KPK market, selected Matrix + Stats, and verified the Exposure column/cells render.
- Desktop
Visual evidence
I updated the existing Leonard screenshot-evidence comment with verified raw PNG links for this head:
#624 (comment)
Review notes
- Prior Leonard blockers were rechecked against the current diff and remain resolved: the shared collateral-open-interest loader has stale-load protection, and sibling consumers now use the shared exposure/open-interest path rather than the earlier duplicate fetch/cache shape.
- The grouped exposure abstraction remains mostly in shared utilities/composables with focused tests, which is the right direction for this surface.
- I left one non-blocking inline maintainability note on the repeated Earn strategy source helper. The current behavior appears safe enough for merge, but the helper is now duplicated across three Earn exposure components and the
!marketKeybranch silently drops an otherwise displayable source label. If that is intentional, fine; otherwise it is a tidy candidate for a shared helper/test.
Smoke coverage: browser visual smoke + mobile smoke; no wallet/signing smoke, since this PR changes read-only exposure presentation and proxy/data plumbing, not transaction construction.
Comment lifecycle: updated the existing Leonard screenshot-evidence comment for the current head; no Leonard-owned inline review comments were present to delete; submitted this fresh formal review for the current head.
| } | ||
| const getStrategyMarketSource = (strategyVault: EVault) => { | ||
| const marketKey = getProductKeyByVault(strategyVault.address) | ||
| if (!marketKey) return undefined |
There was a problem hiding this comment.
Non-blocking maintainability note: this same getStrategyMarketSource helper is now repeated across the Earn row, Earn stats, and Earn exposure components. The helper also drops the source entirely when getProductKeyByVault() has no route key, even though the exposure sources modal can render a non-linked source label. If suppressing unlinked sources is intentional, fine; otherwise consider extracting a shared helper that always returns the label and conditionally adds to, with a small linked-vs-unlinked strategy test. Neat little branch, but it would like a single home.
d6977ef
into
feature/lite-215-convert-vault-page-sections-to-accordion-style
Summary
Changes
Visual review guide
Screenshots compare this branch against
feature/lite-215-convert-vault-page-sections-to-accordion-style. The after screenshots were refreshed from PR #624 preview head04e01cf3.Lend row exposure
Lend row exposure preview
Lend vault Exposure section
Earn row Allocates into
Earn vault Exposure section
Test plan
npm run test:run -- tests/composables/useCollateralOpenInterest.test.ts tests/utils/open-interest.test.ts tests/utils/vault/collateral-exposure.test.ts tests/server/v3-proxy.test.tsnpm run test:run -- tests/utils/vault/exposure-display.test.tsnpm run typechecknpx eslint components/entities/vault/VaultItem.vue components/entities/vault/VaultEarnItem.vue components/entities/vault/overview/VaultOverview.vue components/entities/vault/overview/VaultOverviewBlockBorrow.vue components/entities/vault/overview/earn/VaultOverviewEarnBlockExposure.vue composables/useCollateralOpenInterest.ts utils/vault/collateral-exposure.tsnpx eslint components/entities/vault/VaultExposureSummary.vue components/entities/vault/VaultItem.vue components/entities/vault/VaultEarnItem.vue components/entities/vault/VaultExposureListModal.vue components/entities/vault/overview/VaultOverviewBlockGeneral.vue components/entities/vault/overview/earn/VaultOverviewEarnBlockStats.vue components/entities/vault/overview/earn/VaultOverviewEarnBlockExposure.vue components/entities/vault/discovery/DiscoveryMarketAttributeMatrix.vue utils/vault/exposure-display.ts tests/utils/vault/exposure-display.test.tsnpm run build